package cs340omega;

import java.io.BufferedReader;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class Client extends Thread
{
	/**
	 * 
	 * 
	 * @author djb0646
	 * @version 0.9
	 */
	private static int CLIENT_PORT = 3001;
	private static int SERVER_PORT = 3000;
	/**
	 * 
	 * constructor
	 */
	public Client()
	{
	}
	/**
	 * constructor with param
	 * @param port 
	 *  user defined port number
	 *  
	 */
	public Client(int port)
	{
		CLIENT_PORT = port;
		try
		{
			System.out.println("|client|->run()");
			sendData("localhost", port, "\n\n*************************\n*\n*   Client is running now! "
					+ "   \n*\n*************************");
		}
		catch (IOException e) 
		{
			e.printStackTrace();
		}
		catch (ClassNotFoundException e)
		{
			e.printStackTrace();
		}
	} 
	
	/**
	 *  
	 * @see java.lang.Thread#run()
	 */
	public void run()
	{
		try 
		{
			System.out.println("|client|->run()");
			sendData("localhost", CLIENT_PORT, "\n\n*************************\n*\n*" 
					+ "   Client is running now! "
					+ "   \n*\n*************************");
			
		} 
		catch (IOException e) 
		{
			e.printStackTrace();
		} 
		catch (ClassNotFoundException e) 
		{
			e.printStackTrace();
		}
	}
	
	/**
	 * the method that sends data to target location.
	 * @param location
	 *  Ip /"localhost"/ or your PC name ,for example "John's pc" 
	 * @param message
	 *  string (which is an object)
	 */
	public static Object sendData(String location, int port, Object message) 
		throws IOException, ClassNotFoundException
	{	
		//System.out.println("sendData(): \n location:"+location+"\n message:"+message);
		setLinkToServer(location, port);
		Socket target = new Socket(location, port); 
		
		System.out.println("|client|socket connected:" + target.getRemoteSocketAddress());
		
		ObjectOutputStream output = new ObjectOutputStream(target.getOutputStream()); 
		ObjectInputStream input = new ObjectInputStream(target.getInputStream());
		
		System.out.println("|client|sending data to Server -----" + target.getRemoteSocketAddress());
		
		output.writeObject(message);
		output.flush(); 
		Object result = input.readObject();
		
		
		//if(result instanceof String)
		//{
		//	System.out.println("|client|here is the result back to client:  \n" + (String) result);
		//}
		
		output.close();
		input.close();
		target.close();
		return result;
	}
	/**
	 * 
	 * @param globalid
	 * the target machine and port
	 * @param message
	 * Actuarially the command objects
	 * @return 
	 * The return object we get from remote server
	 * @throws IOException
	 * If connection trouble
	 * @throws ClassNotFoundException
	 * If send /get object in trouble
	 */
	public static Object sendData(GlobalID globalid, Object message) 
		throws IOException, ClassNotFoundException
	{	
		return sendData(globalid.getMachineIP(), globalid.getPort(), message);
	}
	/**
	 *  
	 * @param port 
	 * the port that user passed in 
	 * @param message
	 * Actuarially the command objects
	 * @return 
	 *  no return value 
	 * @throws IOException
	 * If connection trouble
	 * @throws ClassNotFoundException
	 * If send /get object in trouble
	 */
	public static void voidSendData(String location, int port, Object message) throws IOException, ClassNotFoundException
	{	
		//System.out.println("sendData(): \n location:"+location+"\n message:"+message);
		
		setLinkToServer(location, port);
		Socket target = new Socket(location, port);
		
		System.out.println("|client|socket connected:" + target.getRemoteSocketAddress());
		
		ObjectOutputStream output = new ObjectOutputStream(target.getOutputStream()); 
		ObjectInputStream input = new ObjectInputStream(target.getInputStream());
		
		System.out.println("|client|sending data to Server -----" + target.getRemoteSocketAddress());
		
		output.writeObject(message);
		output.flush();   
		output.close();
		input.close();
		target.close();
		
		System.out.println("|client|SendData Request finished\n\n");
		
	}
	/**
	 *  
	 * @param globalid
	 * target machine id
	 * @param message
	 * Actuarially the command objects
	 * @return 
	 *  no return value 
	 * @throws IOException
	 * If connection trouble
	 * @throws ClassNotFoundException
	 * If send /get object in trouble
	 */
	public static void voidSendData(GlobalID globalid, Object message) throws IOException, ClassNotFoundException
	{	
		voidSendData(globalid.getMachineIP(), globalid.getPort(), message);
	}
	/**
	 * 
	 * @param location
	 * location of destiny
	 * @param socket
	 * hearing port of destiny
	 * @return
	 * server's reply
	 * @throws IOException
	 * connection fail
	 * @throws ClassNotFoundException
	 * passing obj fail
	 */
	public static Object setLinkToServer(String location, int socket) throws IOException, ClassNotFoundException
	{
		Socket target = new Socket(location, SERVER_PORT);
		
		System.out.println("|client|Primary socket connected:" + target.getRemoteSocketAddress());
		ObjectOutputStream output = new ObjectOutputStream(target.getOutputStream()); 
		ObjectInputStream input = new ObjectInputStream(target.getInputStream());
		
		//System.out.println("|client|request for a private link between local and "+target.getRemoteSocketAddress());
		 
		output.writeObject("" + socket);
		output.flush(); 
		String result = (String) input.readObject();
		
		System.out.println(result);
		
		output.close();
		input.close();
		target.close();
		
		return result;
	}
	/**
	 * 
	 * @param globalid
	 * location of destiny
	 * @param socket
	 * hearing port of destiny
	 * @return
	 * server's reply
	 * @throws IOException
	 * connection fail
	 * @throws ClassNotFoundException
	 * passing obj fail
	 */
	public static Object setLinkToServer(GlobalID globalid, int socket) throws IOException, ClassNotFoundException
	{		
		return setLinkToServer(globalid.getMachineIP(), socket);
	}
	
	/**
	 * testing driver
	 * @param args
	 * command passin. no use.
	 */
	public static void main(String[] args)
	{
		
		BufferedReader input =  new BufferedReader(new InputStreamReader(System.in));
		 
		try 
		{
			System.out.println("Enter your distiny:");
			
			String location = input.readLine();
			
			System.out.println("Enter your message:");
			
			String message = input.readLine();
			
			System.out.println("Enter your port:");
			
			int port = input.read();
			Client.sendData(location, port, message);
			
		} 
		catch (IOException e)
		{
			e.printStackTrace();
		}
		catch (ClassNotFoundException e)
		{
			e.printStackTrace();
		}
	}
	
}
